package cl.solidit.geomanagement.persistance;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import cl.solidit.geomanagement.persistance.model.Comuna;
import cl.solidit.geomanagement.persistance.model.Persona;
import cl.solidit.geomanagement.persistance.model.Rol;
import cl.solidit.geomanagement.persistance.model.Upload;
import cl.solidit.geomanagement.persistance.model.UploadLog;
import cl.solidit.geomanagement.persistance.util.Rut;

@Repository
public class PersonaDAO {
	@PersistenceContext
	private EntityManager em;
	@Autowired
	private ComunaDAO comunaDAO;
	@Autowired
	private UploadDAO uploadDAO;

	@Transactional
	public Persona createOrUpdate(Persona persona) {
		if (persona.getId() != null && persona.getId() > 0)
			em.merge(persona);
		else
			em.persist(persona);
		return persona;
	}

	public List<Rol> traerRol() {
		TypedQuery<Rol> q = em.createQuery("From Rol", Rol.class);
		List<Rol> resultado = q.getResultList();
		return resultado;
	}

	@Transactional
	public Persona findById(Long id) {
		return em.find(Persona.class, id);
	}

	@Transactional
	public Persona findByApellido(String apellido) {
		TypedQuery<Persona> q = em.createQuery(
				"From Persona p where p.apellido=:apellido", Persona.class);
		q.setParameter("apellido", apellido);
		List<Persona> resultado = q.getResultList();
		if (resultado.size() == 0)
			return null;
		else
			return resultado.get(0);
	}

	@Transactional
	public Persona findByRut(String rut) {
		rut = Rut.format(rut);
		if (rut.trim().length() == 0) {
			return null;
		}
		TypedQuery<Persona> q = em.createQuery(
				"FROM Persona p where p.rut=:rut", Persona.class);
		q.setParameter("rut", rut);
		List<Persona> resultado = q.getResultList();
		if (resultado.size() == 0)
			return null;
		return resultado.get(0);
	}

	@Transactional
	public Persona consultarPersonaByRutParcial(Integer rut) {
		String parcial = rut + "-";
		TypedQuery<Persona> q = em.createQuery(
				"FROM Persona p where p.rut like '" + parcial + "%'",
				Persona.class);
		List<Persona> resultado = q.getResultList();
		if (resultado.size() == 0)
			return null;
		return resultado.get(0);
	}

	@Transactional
	public List<Persona> getAgentes() {
		TypedQuery<Persona> q = em
				.createQuery(
						"SELECT u.persona FROM Usuario u where u.rol.id=2 order by u.persona.nombre asc",
						Persona.class);
		return q.getResultList();
	}

	public static boolean validarRut(Integer rut) {
		boolean validacion = false;
		int m = 0, s = 1;
		for (; rut != 0; rut /= 10) {
			s = (s + rut % 10 * (9 - m++ % 6)) % 11;
		}
		return validacion;
	}

	@Transactional
	public void loadPersona(Long upload, String[] datos) {
		// String ncomuna = datos[8];
		// Comuna comuna = comunaDAO.findByName(ncomuna.toUpperCase());

		// if (comuna == null) {
		// u.getLogs().add(
		// new UploadLog(u, "La comuna " + ncomuna + " no existe"));
		// u.setError(u.getError() + 1);
		// } else {
		Upload u = uploadDAO.byId(upload);
		try {
			String rut = datos[0] + "-" + datos[1];

			boolean newPersona = false;
			Persona persona;
			rut = Rut.format(rut);
			persona = this.findByRut(rut);
			if (persona == null || rut.trim().length() == 0) {
				persona = new Persona();
				persona.setRut(rut);
				persona.setFechaIngreso(new Date());
				newPersona = true;
			}
			persona.setNombre(datos[2]);
			persona.setContacto(datos[3]);
			persona.setFonoOficina(datos[4]);
			persona.setFonoCasa(datos[5]);
			persona.setFonoMovil(datos[6]);
			persona.setDireccion(datos[7]);
			persona.setComuna(new Comuna(Long.parseLong(datos[8].trim())));
			persona.setCiudad(datos[9]);
			persona.setCorreo(datos[10]);
			if (newPersona) {
				this.createOrUpdate(persona);
				u.setInserted(u.getInserted() + 1);
			} else
				u.setUpdated(u.getUpdated() + 1);

		} catch (Exception e) {
			u.getLogs().add(new UploadLog(u, e.getMessage()));
			u.setError(u.getError() + 1);
		}

		u.setDone(u.getDone() + 1);
	}

	@Transactional
	public List<Persona> selectAllPersonas() {
		TypedQuery<Persona> q = em.createQuery("From Persona", Persona.class);
		List<Persona> resultado = q.getResultList();
		return resultado;
	}

}
